// 版权所有2016 Go作者。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package windows

import (
	"syscall"
	"unsafe"
)

const (
	FSCTL_SET_REPARSE_POINT    = 0x000900A4
	IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003

	SYMLINK_FLAG_RELATIVE = 1
)

// 这些结构在https:
// 和https:

type REPARSE_DATA_BUFFER struct {
	ReparseTag        uint32
	ReparseDataLength uint16
	Reserved          uint16
	DUMMYUNIONNAME    byte
}

// 重分析数据缓冲区头是重分析数据缓冲区结构的常见部分。
type REPARSE_DATA_BUFFER_HEADER struct {
	ReparseTag uint32
	// 在
	// 重分析数据缓冲区元素的公共部分之后的重分析数据的大小（以字节为单位）。
	// 此值是从
	// SubstituteNameOffset字段开始的数据长度。
	ReparseDataLength uint16
	Reserved          uint16
}

type SymbolicLinkReparseBuffer struct {
	// 包含替换名称字符串在PathBuffer数组中的偏移量的整数，以字节为单位，
	// 计算为从PathBuffer的字节0的偏移量。注意
	// 这个偏移量必须除以2才能得到数组索引。
	SubstituteNameOffset uint16
	// 包含替换名称字符串长度（以字节为单位）的整数。如果此字符串以null结尾，
	// SubstituteNameLength不包括Unicode空字符。
	SubstituteNameLength uint16
	// PrintNameOffset类似于SubstituteNameOffset。
	PrintNameOffset uint16
	// PrintNameLength类似于SubstituteNameLength。
	PrintNameLength uint16
	// 标志指定替代名称是完整路径名还是
	// 相对于包含符号链接的目录的路径名。
	Flags      uint32
	PathBuffer [1]uint16
}

// Path返回存储在rb中的路径。
func (rb *SymbolicLinkReparseBuffer) Path() string {
	n1 := rb.SubstituteNameOffset / 2
	n2 := (rb.SubstituteNameOffset + rb.SubstituteNameLength) / 2
	return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(&rb.PathBuffer[0]))[n1:n2:n2])
}

type MountPointReparseBuffer struct {
	// 包含替换名称字符串在PathBuffer数组中的偏移量的整数，以字节为单位，
	// 计算为从PathBuffer的字节0的偏移量。注意
	// 这个偏移量必须除以2才能得到数组索引。
	SubstituteNameOffset uint16
	// 包含替换名称字符串长度（以字节为单位）的整数。如果此字符串以null结尾，
	// SubstituteNameLength不包括Unicode空字符。
	SubstituteNameLength uint16
	// PrintNameOffset类似于SubstituteNameOffset。
	PrintNameOffset uint16
	// PrintNameLength类似于SubstituteNameLength。
	PrintNameLength uint16
	PathBuffer      [1]uint16
}

// Path返回存储在rb中的路径。
func (rb *MountPointReparseBuffer) Path() string {
	n1 := rb.SubstituteNameOffset / 2
	n2 := (rb.SubstituteNameOffset + rb.SubstituteNameLength) / 2
	return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(&rb.PathBuffer[0]))[n1:n2:n2])
}
